﻿using UnityEngine;
using System.Collections;

public class LightRequest : MonoBehaviour {

  enum PlayerState {
    InLight = 0,
    JustInDark,
    GetHurt,
    Dead,
  };

  private PlayerState playerState = PlayerState.InLight;

  public float timeToGetHurtInDarkInS= 1.0f;
  public float timeToDieInHurInS = 2.0f;

  private float timeInDarkInS = 0.0f;
  private float timeInHurtInS = 0.0f;

  public MeshRenderer indicator;

  // vignet
  public float vignetInLight = 0.0f;
  public float vignetJustInDark = 80.0f;
  public float vignetGetHurt = 150.0f;

  // brightness
  public float brightnessInLight = 1.0f;
  public float brightnessJustInDark = 0.3f;
  public float brightnessGetHurt = 0.05f;

  // movement
  public float walkSpeedInLight = 1.0f;
  public float walkSpeedJustInDark = 1.0f;
  public float walkSpeedGetHurt = 0.3f;

  // saturation
  public float saturationInLight = 0.9f;
  public float saturationJustInDark = 0.5f;
  public float saturationGetHurt = 0.1f;

  public void Die () {
    ToDead();
  }

  public void Revive () {
    // if state is dead, ToInLight will do nothing
    playerState = PlayerState.InLight;
    ToInLight();
    Respawn respawn = GetComponent<Respawn>();
    if (respawn) {
      respawn.DoRespawn();
    }
  }

  // Use this for initialization
  void Start () {
  
  }

  private void ToInLight () {
    if (playerState != PlayerState.Dead) {
      playerState = PlayerState.InLight;
      timeInDarkInS = 0.0f;
      timeInHurtInS = 0.0f;
    }
  }

  private void ToJustInDark () {
    playerState = PlayerState.JustInDark;
    timeInDarkInS = 0.0f;
  }

  private void ToGetHurt () {
    playerState = PlayerState.GetHurt;
    timeInHurtInS = 0.0f;
  }

  private void ToDead () {
    playerState = PlayerState.Dead;
    Revive();
  }

  // Update is called once per frame
  void Update () {
    updatePlayerState();
    updateBrightness();
    updateVignett();
    updateMovement();
    updateIndicator();
    updateSaturation();
  }

  private void updatePlayerState () {
    if (LightSensor.IsInAnyLight(transform.position, gameObject)) {
      // in light
      if (playerState != PlayerState.Dead) {
        ToInLight();
      }
    }
    else {
      // in dark
      float deltaTimeInS = Time.deltaTime;
      while (deltaTimeInS > 0.0f) {
        if (playerState == PlayerState.InLight) {
          ToJustInDark();
        }
        else if (playerState == PlayerState.JustInDark) {
          timeInDarkInS += deltaTimeInS;
          if (timeInDarkInS > timeToGetHurtInDarkInS) {
            ToGetHurt();
            deltaTimeInS -= timeInDarkInS - timeToGetHurtInDarkInS;
          }
          else {
            // use up delta time
            break;
          }
        }
        else if (playerState == PlayerState.GetHurt) {
          timeInHurtInS += deltaTimeInS;
          if (timeInHurtInS > timeToDieInHurInS) {
            ToDead();
          }
          // use up delta time or dead, go out of loop
          break;
        }
        else if (playerState == PlayerState.Dead) {
          break;
        }
        else {
          Debug.LogError("Unknown playerState.");
        }
      }
    }
  }

  private void updateBrightness () {
    BrightnessEffect brightness = Camera.main.GetComponent<BrightnessEffect>();
    if (brightness) {
      if (playerState == PlayerState.InLight) {
        brightness.Brightness = Mathf.Lerp(brightness.Brightness, brightnessInLight, Time.deltaTime * 4.0f);
      }
      else if (playerState == PlayerState.JustInDark) {
        brightness.Brightness = Mathf.Lerp(brightness.Brightness, brightnessJustInDark, Time.deltaTime * 3.0f);
      }
      else if (playerState == PlayerState.GetHurt) {
        brightness.Brightness = Mathf.Lerp(brightness.Brightness, brightnessGetHurt, Time.deltaTime);
      }
      else if (playerState == PlayerState.Dead) {
        brightness.Brightness = Mathf.Lerp(brightness.Brightness, brightnessGetHurt, Time.deltaTime * 5.0f);
      }
    }
  }

  private void updateVignett () {
    Vignetting vignetting = Camera.main.GetComponent<Vignetting>();
    if (vignetting) {
      if (playerState == PlayerState.InLight) {
        vignetting.intensity = Mathf.Lerp(vignetting.intensity, vignetInLight, Time.deltaTime * 4.0f);
      }
      else if (playerState == PlayerState.JustInDark) {
        vignetting.intensity = Mathf.Lerp(vignetting.intensity, vignetJustInDark, Time.deltaTime * 3.0f);
      }
      else if (playerState == PlayerState.GetHurt) {
        vignetting.intensity = Mathf.Lerp(vignetting.intensity, vignetGetHurt, Time.deltaTime);
      }
      else if (playerState == PlayerState.Dead) {
        vignetting.intensity = Mathf.Lerp(vignetting.intensity, vignetGetHurt, Time.deltaTime * 5.0f);
      }
    } 
  }

  private void updateMovement () {
    ThirdPersonController controller = gameObject.GetComponent<ThirdPersonController>();
    if (controller) {
      if (playerState == PlayerState.InLight) {
        controller.walkSpeed = Mathf.Lerp(controller.walkSpeed, walkSpeedInLight, Time.deltaTime * 4.0f);
      }
      else if (playerState == PlayerState.JustInDark) {
        controller.walkSpeed = Mathf.Lerp(controller.walkSpeed, walkSpeedJustInDark, Time.deltaTime * 3.0f);
      }
      else if (playerState == PlayerState.GetHurt) {
        controller.walkSpeed = Mathf.Lerp(controller.walkSpeed, walkSpeedGetHurt, Time.deltaTime);
      }
    }
  }

  private void updateIndicator () {
    if (indicator) {
      if (playerState == PlayerState.InLight) {
        indicator.material.color = Color.gray;
      }
      else if (playerState == PlayerState.JustInDark) {
        indicator.material.color = Color.green;
      }
      else if (playerState == PlayerState.GetHurt) {
        indicator.material.color = Color.yellow;
      }
      else {
        indicator.material.color = Color.red;
      }
    }
  }

  private void updateSaturation () {
    ColorCorrectionCurves colorCorrectionCurves =
      Camera.main.GetComponent<ColorCorrectionCurves>();
    if (colorCorrectionCurves) {
      if (playerState == PlayerState.InLight) {
        colorCorrectionCurves.saturation =
          Mathf.Lerp(colorCorrectionCurves.saturation,
          saturationInLight,
          Time.deltaTime * 4.0f);
      }
      else if (playerState == PlayerState.JustInDark) {
        colorCorrectionCurves.saturation =
          Mathf.Lerp(colorCorrectionCurves.saturation,
          saturationJustInDark,
          Time.deltaTime * 3.0f);
      }
      else if (playerState == PlayerState.GetHurt) {
        colorCorrectionCurves.saturation =
          Mathf.Lerp(colorCorrectionCurves.saturation,
          saturationGetHurt,
          Time.deltaTime);
      }
      else if (playerState == PlayerState.Dead) {
        colorCorrectionCurves.saturation =
          Mathf.Lerp(colorCorrectionCurves.saturation,
          saturationGetHurt,
          Time.deltaTime * 5.0f);
      }
    }
  }
}
